1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the
10   * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11   * express or implied. See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package com.google.common.collect;
16  
17  import com.google.common.annotations.Beta;
18  
19  import java.util.NoSuchElementException;
20  import java.util.Set;
21  
22  import javax.annotation.Nullable;
23  
24  /**
25   * A set comprising zero or more {@linkplain Range#isEmpty nonempty},
26   * {@linkplain Range#isConnected(Range) disconnected} ranges of type {@code C}.
27   *
28   * <p>Implementations that choose to support the {@link #add(Range)} operation are required to
29   * ignore empty ranges and coalesce connected ranges.  For example:  <pre>   {@code
30   *
31   *   RangeSet<Integer> rangeSet = TreeRangeSet.create();
32   *   rangeSet.add(Range.closed(1, 10)); // {[1, 10]}
33   *   rangeSet.add(Range.closedOpen(11, 15)); // disconnected range; {[1, 10], [11, 15)}
34   *   rangeSet.add(Range.closedOpen(15, 20)); // connected range; {[1, 10], [11, 20)}
35   *   rangeSet.add(Range.openClosed(0, 0)); // empty range; {[1, 10], [11, 20)}
36   *   rangeSet.remove(Range.open(5, 10)); // splits [1, 10]; {[1, 5], [10, 10], [11, 20)}}</pre>
37   *
38   * <p>Note that the behavior of {@link Range#isEmpty()} and {@link Range#isConnected(Range)} may
39   * not be as expected on discrete ranges.  See the Javadoc of those methods for details.
40   *
41   * <p>For a {@link Set} whose contents are specified by a {@link Range}, see {@link ContiguousSet}.
42   *
43   * @author Kevin Bourrillion
44   * @author Louis Wasserman
45   * @since 14.0
46   */
47  @Beta
48  public interface RangeSet<C extends Comparable> {
49    
50    // Query methods
51  
52    /**
53     * Determines whether any of this range set's member ranges contains {@code value}.
54     */
55    boolean contains(C value);
56  
57    /**
58     * Returns the unique range from this range set that {@linkplain Range#contains contains}
59     * {@code value}, or {@code null} if this range set does not contain {@code value}.
60     */
61    Range<C> rangeContaining(C value);
62  
63    /**
64     * Returns {@code true} if there exists a member range in this range set which
65     * {@linkplain Range#encloses encloses} the specified range.
66     */
67    boolean encloses(Range<C> otherRange);
68  
69    /**
70     * Returns {@code true} if for each member range in {@code other} there exists a member range in
71     * this range set which {@linkplain Range#encloses encloses} it. It follows that
72     * {@code this.contains(value)} whenever {@code other.contains(value)}. Returns {@code true} if
73     * {@code other} is empty.
74     *
75     * <p>This is equivalent to checking if this range set {@link #encloses} each of the ranges in
76     * {@code other}.
77     */
78    boolean enclosesAll(RangeSet<C> other);
79  
80    /**
81     * Returns {@code true} if this range set contains no ranges.
82     */
83    boolean isEmpty();
84  
85    /**
86     * Returns the minimal range which {@linkplain Range#encloses(Range) encloses} all ranges
87     * in this range set.
88     *
89     * @throws NoSuchElementException if this range set is {@linkplain #isEmpty() empty}
90     */
91    Range<C> span();
92  
93    // Views
94    
95    /**
96     * Returns a view of the {@linkplain Range#isConnected disconnected} ranges that make up this
97     * range set.  The returned set may be empty. The iterators returned by its
98     * {@link Iterable#iterator} method return the ranges in increasing order of lower bound
99     * (equivalently, of upper bound).
100    */
101   Set<Range<C>> asRanges();
102 
103   /**
104    * Returns a view of the complement of this {@code RangeSet}.
105    *
106    * <p>The returned view supports the {@link #add} operation if this {@code RangeSet} supports
107    * {@link #remove}, and vice versa.
108    */
109   RangeSet<C> complement();
110   
111   /**
112    * Returns a view of the intersection of this {@code RangeSet} with the specified range.
113    *
114    * <p>The returned view supports all optional operations supported by this {@code RangeSet}, with
115    * the caveat that an {@link IllegalArgumentException} is thrown on an attempt to
116    * {@linkplain #add(Range) add} any range not {@linkplain Range#encloses(Range) enclosed} by
117    * {@code view}.
118    */
119   RangeSet<C> subRangeSet(Range<C> view);
120   
121   // Modification
122 
123   /**
124    * Adds the specified range to this {@code RangeSet} (optional operation). That is, for equal
125    * range sets a and b, the result of {@code a.add(range)} is that {@code a} will be the minimal
126    * range set for which both {@code a.enclosesAll(b)} and {@code a.encloses(range)}.
127    *
128    * <p>Note that {@code range} will be {@linkplain Range#span(Range) coalesced} with any ranges in
129    * the range set that are {@linkplain Range#isConnected(Range) connected} with it.  Moreover,
130    * if {@code range} is empty, this is a no-op.
131    *
132    * @throws UnsupportedOperationException if this range set does not support the {@code add}
133    *         operation
134    */
135   void add(Range<C> range);
136 
137   /**
138    * Removes the specified range from this {@code RangeSet} (optional operation). After this
139    * operation, if {@code range.contains(c)}, {@code this.contains(c)} will return {@code false}.
140    *
141    * <p>If {@code range} is empty, this is a no-op.
142    *
143    * @throws UnsupportedOperationException if this range set does not support the {@code remove}
144    *         operation
145    */
146   void remove(Range<C> range);
147   
148   /**
149    * Removes all ranges from this {@code RangeSet} (optional operation).  After this operation,
150    * {@code this.contains(c)} will return false for all {@code c}.
151    * 
152    * <p>This is equivalent to {@code remove(Range.all())}.
153    * 
154    * @throws UnsupportedOperationException if this range set does not support the {@code clear}
155    *         operation
156    */
157   void clear();
158 
159   /**
160    * Adds all of the ranges from the specified range set to this range set (optional operation).
161    * After this operation, this range set is the minimal range set that
162    * {@linkplain #enclosesAll(RangeSet) encloses} both the original range set and {@code other}.
163    *
164    * <p>This is equivalent to calling {@link #add} on each of the ranges in {@code other} in turn.
165    *
166    * @throws UnsupportedOperationException if this range set does not support the {@code addAll}
167    *         operation
168    */
169   void addAll(RangeSet<C> other);
170 
171   /**
172    * Removes all of the ranges from the specified range set from this range set (optional
173    * operation). After this operation, if {@code other.contains(c)}, {@code this.contains(c)} will
174    * return {@code false}.
175    *
176    * <p>This is equivalent to calling {@link #remove} on each of the ranges in {@code other} in
177    * turn.
178    *
179    * @throws UnsupportedOperationException if this range set does not support the {@code removeAll}
180    *         operation
181    */
182   void removeAll(RangeSet<C> other);
183   
184   // Object methods
185 
186   /**
187    * Returns {@code true} if {@code obj} is another {@code RangeSet} that contains the same ranges
188    * according to {@link Range#equals(Object)}.
189    */
190   @Override
191   boolean equals(@Nullable Object obj);
192   
193   /**
194    * Returns {@code asRanges().hashCode()}.
195    */
196   @Override
197   int hashCode();
198 
199   /**
200    * Returns a readable string representation of this range set. For example, if this
201    * {@code RangeSet} consisted of {@code Range.closed(1, 3)} and {@code Range.greaterThan(4)},
202    * this might return {@code " [1‥3](4‥+∞)}"}.
203    */
204   @Override
205   String toString();
206 }